from datetime import datetime
import logging
from controllers.errors.online_mall.pick_addr_errors import HPickAddrNotFoundError, HPickAddrParamError
from controllers.errors.online_mall.shop_errors import HShopNotFoundError
from flask_babel import _
from core.entities.account_role import AccountWrap
from extensions.ext_database import db
from werkzeug.exceptions import InternalServerError
from models.online_mall.delivery import MPickAddr
from models.online_mall.shop_msg import MShop
from services.area_init_service import AreaService

class PickAddrService:
    @staticmethod
    def get_list(account:AccountWrap,args:dict)->dict:
        try:
            tenant_id = account.current_tenant_id
            query = db.session.query(MPickAddr).filter(MPickAddr.tenant_id==tenant_id)
            total = 0
            has_more = False
            if 'id' in args and args['id']:
                query = query.filter(MPickAddr.id==args['id'])
                total = query.count()
            else:
                if 'name' in args and args['name']:
                    query = query.filter(MPickAddr.name.ilike(f"%{args['name']}%"))
                if 'addr' in args and args['addr']:
                    query = query.filter(MPickAddr.addr.ilike(f"%{args['addr']}%"))
                if 'mobile' in args and args['mobile']:
                    query = query.filter(MPickAddr.mobile.ilike(f"%{args['mobile']}%"))
                if 'province_id' in args and args['province_id']:
                    query = query.filter(MPickAddr.province_id==args['province_id'])
                if 'city_id' in args and args['city_id']:
                    query = query.filter(MPickAddr.city_id==args['city_id'])
                if 'district_id' in args and args['district_id']:
                    query = query.filter(MPickAddr.district_id==args['district_id'])
                if 'province' in args and args['province']:
                    query = query.filter(MPickAddr.province.like(f"%{args['province']}%"))
                if 'city' in args and args['city']:
                    query = query.filter(MPickAddr.city.like(f"%{args['city']}%"))
                if 'district' in args and args['district']:
                    query = query.filter(MPickAddr.district.like(f"%{args['district']}%"))
                if 'shop_id' in args and args['shop_id']:
                    query = query.filter(MPickAddr.shop_id==args['shop_id'])
                total = query.count()
                page = args.get('page')
                page_size = args.get('page_size')
                if page and page_size and page >0 and page_size >0:
                    query = query.offset((page-1)*page_size).limit(page_size)
                    has_more = total > page*page_size
            data = query.all()
            return {
                "total":total,
                "has_more":has_more,
                "data":data
            }
        except Exception as e:
            logging.error(e)
            return {
                "total":0,
                "has_more":False,
                "data":[],
                "message":str(e)
            }
        
    @staticmethod
    def create_addr(account:AccountWrap,args:dict)->MPickAddr:
        if not account or not isinstance(account,AccountWrap):
            raise NotLoginError()
        addr = MPickAddr(
                tenant_id = account.current_tenant_id, # type:ignore
                created_by = account.id, # type:ignore
            )
        PickAddrService._fill_addr_params(args, addr)
        try:
            db.session.add(addr)
            db.session.commit()
            return addr
        except Exception as e:
            db.session.rollback()
            raise InternalServerError(str(e))

    @staticmethod
    def update_addr(account:AccountWrap,args:dict)->MPickAddr:
        if not account or not isinstance(account,AccountWrap):
            raise NotLoginError()
        addr_id = args.get("id")
        if not addr_id:
            raise HPickAddrNotFoundError(addr_id)
        addr = db.session.get(MPickAddr,addr_id)
        if not addr:
            raise HPickAddrNotFoundError(addr_id)
        PickAddrService._fill_addr_params(args, addr)
        addr.updated_at = datetime.now()
        addr.updated_by = account.id
        try:
            db.session.commit()
            return addr
        except Exception as e:
            db.session.rollback()
            raise InternalServerError(str(e))
        
    @staticmethod
    def delete_addr(account:AccountWrap,addr_id)->MPickAddr:
        if not account or not isinstance(account,AccountWrap):
            raise NotLoginError()

        if not addr_id:
            raise HPickAddrNotFoundError(addr_id)
        addr = db.session.get(MPickAddr,addr_id)
        if not addr:
            raise HPickAddrNotFoundError(addr_id)
        try:
            db.session.delete(addr)
            db.session.commit()
            return addr
        except Exception as e:
            db.session.rollback()
            raise InternalServerError(str(e))
    @staticmethod
    def _fill_addr_params(args, addr):
        if 'name' in args and args['name']:
            addr.name = args['name']
        else:
            raise HPickAddrParamError(_("Pick up address name cannot be empty"))
        if 'addr' in args and args['addr']:
            addr.addr = args['addr']
        else:
            raise HPickAddrParamError(_("Pick up address cannot be empty"))
        if 'mobile' in args and args['mobile']:
            addr.mobile = args['mobile']
        else:
            raise HPickAddrParamError(_("Mobile number cannot be empty."))
        if 'province_id' in args and args['province_id']:
            addr.province_id = args['province_id']
            addr.province = AreaService.get_area_name_by_code(args['province_id'])
        if 'city_id' in args and args['city_id']:
            addr.city_id = args['city_id']
            addr.city = AreaService.get_area_name_by_code(args['city_id'])
        if 'district_id' in args and args['district_id']:
            addr.district_id = args['district_id']
            addr.district = AreaService.get_area_name_by_code(args['district_id'])
        # if 'province' in args and args['province']:
        #     addr.province = args['province']
        # if 'city' in args and args['city']:
        #     query = query.filter(MPickAddr.city.like(f"%{args['city']}%"))
        # if 'district' in args and args['district']:
        #     query = query.filter(MPickAddr.district.like(f"%{args['district']}%"))
        if 'shop_id' in args and args['shop_id']:
            shop = db.session.get(MShop, args['shop_id'])
            if not shop:
                raise HShopNotFoundError(args['shop_id'])
            addr.shop_id = shop.id